package com.example.weblending.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.weblending.domain.ApplyCondition;
import com.example.weblending.domain.User;
import com.example.weblending.exception.GlobalException;
import com.example.weblending.service.ApplyConditionService;
import com.example.weblending.mapper.ApplyConditionMapper;
import com.example.weblending.service.PostService;
import com.example.weblending.service.RemoteService;
import com.example.weblending.utils.CsvUtils;
import com.example.weblending.vo.AnalyzeColumn;
import com.example.weblending.vo.CsvInputColumn;
import feign.Feign;
import feign.Request;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
* @author Administrator
* @description 针对表【apply_condition】的数据库操作Service实现
* @createDate 2023-05-01 19:36:24
*/
@Service
public class ApplyConditionServiceImpl extends ServiceImpl<ApplyConditionMapper, ApplyCondition>
    implements ApplyConditionService{

    @Autowired
    private CsvUtils csvUtils;

    @Resource(name = "lengdingProductServiceImpl")
    private PostService postService;

    /**
     * 获得自己的成功率查询申请列表 （重点： 还没有被处理的）
     */
    @Override
    public Page<ApplyCondition> getList(long page, long limit, User user) {
        QueryWrapper<ApplyCondition> wrapper=new QueryWrapper<>();
        wrapper.eq("uid",user.getUid());
        wrapper.eq("state",0);
        wrapper.orderByDesc("apply_time");
        Page<ApplyCondition> conditionPage=new Page<>(page,limit);
        baseMapper.selectPage(conditionPage,wrapper);
        return conditionPage;
    }

    /**
     * 获得自己的成功率查询申请列表 （重点： 已经被处理的）
     */
    @Override
    public Page<ApplyCondition> getHistory(long page, long limit, User user) {
        QueryWrapper<ApplyCondition> wrapper=new QueryWrapper<>();
        wrapper.eq("uid",user.getUid());
        wrapper.ne("state",0);
        wrapper.orderByDesc("apply_time");
        Page<ApplyCondition> conditionPage=new Page<>(page,limit);
        baseMapper.selectPage(conditionPage,wrapper);
        return conditionPage;
    }

    /**
     * 获得等待处理的查询列表
     */
    @Override
    public Page<ApplyCondition> getExamine(long page, long limit, User user) {
        QueryWrapper<ApplyCondition> wrapper=new QueryWrapper<>();
        wrapper.eq("state",0);
        wrapper.orderByDesc("apply_time");
        Page<ApplyCondition> conditionPage=new Page<>(page,limit);
        baseMapper.selectPage(conditionPage,wrapper);
        return conditionPage;
    }

    /**
     * 获得自己已经处理的查询列表
     */
    @Override
    public Page<ApplyCondition> getApprove(long page, long limit, User user) {
        QueryWrapper<ApplyCondition> wrapper=new QueryWrapper<>();
        wrapper.eq("oid",user.getUid());
        wrapper.ne("uid",user.getUid());
        wrapper.ne("state",0);
        wrapper.orderByDesc("operate_time");
        Page<ApplyCondition> conditionPage=new Page<>(page,limit);
        baseMapper.selectPage(conditionPage,wrapper);
        return conditionPage;
    }

    /**
     * 接受的参数是查询条件对象，将查询条件转成json字符串再保存在数据库
     */
    @Override
    public ApplyCondition apply(CsvInputColumn condition, User user) {
        ApplyCondition applyCondition=new ApplyCondition();
        applyCondition.setUid(user.getUid());
        applyCondition.setState(0);
        applyCondition.setApplyTime(new Timestamp(System.currentTimeMillis()));
        applyCondition.setConditionJson(JSONObject.toJSONString(condition));
        if(condition.getId()!=0){
            applyCondition.setProduct(condition.getId());
            applyCondition.setProductName(postService.getById(condition.getId()).getTitle());
        }else{
            applyCondition.setProductName("自定义");
        }
        if (user.getPermission()==1){
            applyCondition.setOid(user.getUid());
            applyCondition.setState(1);
        }
        if(!this.save(applyCondition)){
            throw new GlobalException(500,"创建申请失败，请联系稍后重试");
        }
        return applyCondition;
    }

    /**
     * 设置状态，通过，拒绝走这个
     */
    @Override
    public boolean setState(int id, int state, User user) {
        ApplyCondition applyCondition=getById(id);
        applyCondition.setState(state);
        applyCondition.setOid(user.getUid());
        applyCondition.setOperateTime(new Timestamp(System.currentTimeMillis()));
        if (state==1){
            applyCondition.setResult(this.analyze(applyCondition));
            applyCondition.setAnalyzeTime(new Timestamp(System.currentTimeMillis()));
        }
        return updateById(applyCondition);
    }

    /**
     * 重新生成成功率，并更新数据库中记录 （同步的）
     */
    @Override
    public boolean refresh(String id, User user) {
        ApplyCondition applyCondition=this.getById(id);
        if (applyCondition.getUid()!=user.getUid()){
            throw new GlobalException(403,"您无权操作");
        }
        applyCondition.setResult(this.analyze(applyCondition));
        applyCondition.setAnalyzeTime(new Timestamp(System.currentTimeMillis()));
        return updateById(applyCondition);
    }

    /**
     * 异步的更新，因为异步任务不能有返回值
     */
    @Async
    @Override
    public void refreshAsync(ApplyCondition applyCondition) {
        applyCondition.setResult(this.analyze(applyCondition));
        applyCondition.setAnalyzeTime(new Timestamp(System.currentTimeMillis()));
        updateById(applyCondition);
    }

    /**
     * 删除记录，直接删除数据库中记录
     */
    @Override
    public boolean delete(int[] ids, User user) {
        for (int i:ids) {
            ApplyCondition a=this.getById(i);
            if(a.getUid()!=user.getUid()){
                throw new GlobalException(403,"您无权操作");
            }else{
                removeById(i);
            }
        }
        return true;
    }

    /**
     * 生成成功路的方法，具体为生成csv，再走 清洗任务，分析任务
     * 因为只有一条数据，需要的时间较少
     * 所以讲所有的流程作为一个任务，不需要用 task去记录
     */
    private Float analyze(ApplyCondition applyCondition){
        //在成功路查询对象中获得查询条件并重新生成查询条件对象
        String condition=applyCondition.getConditionJson();
        CsvInputColumn analyzeColumn= JSONObject.parseObject(condition,CsvInputColumn.class);
        //设置查询条件的其他默认值
        this.defaultValue(analyzeColumn);
        //将该条查询条件做成 csv文件
        List<CsvInputColumn> list=new ArrayList<>();
        list.add(analyzeColumn);
        String inputpath=csvUtils.exportToFile(list);
        //构造 api客户端去调取python服务获得结果
        RemoteService service = Feign.builder()
                .options(new Request.Options(100000, 350000))//设置超时时间
                .target(RemoteService.class,   //代理对象
                        "http://localhost:8000/"); //目标地址
        try{
            //获得到最后的文件
            String analyzePath =service.getFile(inputpath);
            String washPath =analyzePath.replace("/resultfinal/","/wash/");
            java.io.File result=new java.io.File(analyzePath);
            //保存该条记录的成功率
            AtomicReference<Float> resultPercent=new AtomicReference<>();
            EasyExcel.read(result, AnalyzeColumn.class, new PageReadListener<AnalyzeColumn>(dataList -> {
               resultPercent.set(dataList.get(0).getIs());
            })).excelType(ExcelTypeEnum.CSV).sheet().doRead();
            //删除中间过程生成的文件
            java.io.File files = new java.io.File(inputpath);
            if(files.exists()){
                files.delete();
            }
            files = result;
            if(files.exists()){
                files.delete();
            }
            files = new java.io.File(washPath);
            if(files.exists()){
                files.delete();
            }
            //返回最后的成功率
            return resultPercent.get();
        }
        catch (Exception e){
            return 0.0F;
        }
    }

    /**
     * 设置不可配置的查询条件的默认值
     */
    private void defaultValue(CsvInputColumn condition){
        condition.setGrade(3);
        condition.setSubGrade("B3");
        condition.setEmploymentTitle(7755);
        condition.setVerificationStatus(1);
        condition.setIssueDate(null);
        condition.setIsDefault(0);
        condition.setPurpose(0);
        condition.setPostCode(203);
        condition.setRegionCode(14);
        condition.setDti(17.61F);
        condition.setDelinquency_2years(0);
        condition.setFicoRangeLow(690);
        condition.setFicoRangeHigh(694);
        condition.setOpenAcc(11);
        condition.setPubRec(0);
        condition.setPubRecBankruptcies(0);
        condition.setRevolBal(11132);
        condition.setRevolUtil(52.1F);
        condition.setTotalAcc(23);
        condition.setInitialListStatus(0);
        condition.setApplicationType(0);
        condition.setEarliesCreditLine("May-2002");
        condition.setTitle(1);
        condition.setPubRecBankruptcies(1);
    }
}




